package com.zenithmind.disk.pojo.vo;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.zenithmind.disk.enums.ShareStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;

/**
 * 文件分享信息视图对象
 * 遵循单一职责原则：专注于分享数据展示
 * 遵循开闭原则：通过方法封装便于扩展
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "文件分享信息VO")
public class ShareVO {

    @Schema(description = "分享ID")
    private String id;

    @Schema(description = "用户ID")
    private String userId;

    @Schema(description = "文件ID")
    private String fileId;

    @Schema(description = "文件名称")
    private String fileName;

    @Schema(description = "文件类型")
    private String fileType;

    @Schema(description = "文件大小（字节）")
    private Long fileSize;

    @Schema(description = "是否为目录")
    private Boolean isDirectory;

    @Schema(description = "分享码")
    private String shareCode;

    @Schema(description = "分享链接")
    private String shareUrl;

    @Schema(description = "过期时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime expireTime;

    @Schema(description = "访问次数")
    private Integer accessCount;

    @Schema(description = "是否公开")
    private Boolean isPublic;

    @Schema(description = "提取密码（敏感信息，前端不显示）")
    @JsonIgnore
    private String password;

    @Schema(description = "分享状态：0已取消，1有效")
    private Integer status;

    @Schema(description = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;

    // ==================== 扩展字段 ====================

    @Schema(description = "格式化的文件大小")
    private String formattedFileSize;

    @Schema(description = "分享状态描述")
    private String statusDescription;

    @Schema(description = "分享类型描述")
    private String shareTypeDescription;

    @Schema(description = "过期状态描述")
    private String expireStatusDescription;

    @Schema(description = "是否有密码保护")
    private Boolean hasPassword;

    @Schema(description = "剩余有效时间（小时）")
    private Long remainingHours;

    // ==================== 业务方法 ====================

    /**
     * 检查是否为公开分享
     * @return true如果是公开分享
     */
    public boolean isPublicShare() {
        return Boolean.TRUE.equals(isPublic);
    }

    /**
     * 检查是否为私密分享
     * @return true如果是私密分享
     */
    public boolean isPrivateShare() {
        return !isPublicShare();
    }

    /**
     * 检查是否为目录分享
     * @return true如果是目录分享
     */
    public boolean isDirectoryShare() {
        return Boolean.TRUE.equals(isDirectory);
    }

    /**
     * 检查是否为文件分享
     * @return true如果是文件分享
     */
    public boolean isFileShare() {
        return !isDirectoryShare();
    }

    /**
     * 检查分享是否已过期
     * @return true如果已过期
     */
    public boolean isExpired() {
        return expireTime != null && LocalDateTime.now().isAfter(expireTime);
    }

    /**
     * 检查分享是否有效
     * @return true如果有效
     */
    public boolean isValid() {
        return status != null && status == 1 && !isExpired();
    }

    /**
     * 检查是否有密码保护
     * @return true如果有密码保护
     */
    public boolean hasPasswordProtection() {
        if (hasPassword != null) {
            return hasPassword;
        }

        this.hasPassword = isPrivateShare() && StringUtils.isNotBlank(password);
        return hasPassword;
    }

    /**
     * 获取格式化的文件大小
     * @return 格式化后的文件大小字符串
     */
    public String getFormattedFileSize() {
        if (formattedFileSize != null) {
            return formattedFileSize;
        }

        if (fileSize == null || fileSize <= 0 || isDirectoryShare()) {
            this.formattedFileSize = "-";
            return formattedFileSize;
        }

        String[] units = {"B", "KB", "MB", "GB", "TB"};
        double size = fileSize.doubleValue();
        int unitIndex = 0;

        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }

        this.formattedFileSize = String.format("%.2f %s", size, units[unitIndex]);
        return formattedFileSize;
    }

    /**
     * 获取分享状态描述
     * @return 分享状态描述
     */
    public String getStatusDescription() {
        if (statusDescription != null) {
            return statusDescription;
        }

        if (status == null) {
            this.statusDescription = "未知";
            return statusDescription;
        }

        try {
            ShareStatus shareStatus = ShareStatus.fromCode(status);
            this.statusDescription = shareStatus.getDescription();
        } catch (IllegalArgumentException e) {
            this.statusDescription = "未知状态";
        }

        return statusDescription;
    }

    /**
     * 获取分享类型描述
     * @return 分享类型描述
     */
    public String getShareTypeDescription() {
        if (shareTypeDescription != null) {
            return shareTypeDescription;
        }

        if (isPublicShare()) {
            this.shareTypeDescription = "公开分享";
        } else {
            this.shareTypeDescription = "私密分享";
        }

        return shareTypeDescription;
    }

    /**
     * 获取过期状态描述
     * @return 过期状态描述
     */
    public String getExpireStatusDescription() {
        if (expireStatusDescription != null) {
            return expireStatusDescription;
        }

        if (expireTime == null) {
            this.expireStatusDescription = "永久有效";
            return expireStatusDescription;
        }

        if (isExpired()) {
            this.expireStatusDescription = "已过期";
        } else {
            long hours = getRemainingHours();
            if (hours > 24) {
                long days = hours / 24;
                this.expireStatusDescription = "剩余" + days + "天";
            } else {
                this.expireStatusDescription = "剩余" + hours + "小时";
            }
        }

        return expireStatusDescription;
    }

    /**
     * 获取剩余有效时间（小时）
     * @return 剩余小时数
     */
    public long getRemainingHours() {
        if (remainingHours != null) {
            return remainingHours;
        }

        if (expireTime == null) {
            this.remainingHours = Long.MAX_VALUE; // 永不过期
            return remainingHours;
        }

        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(expireTime)) {
            this.remainingHours = 0L; // 已过期
        } else {
            this.remainingHours = java.time.Duration.between(now, expireTime).toHours();
        }

        return remainingHours;
    }

    /**
     * 获取文件扩展名
     * @return 文件扩展名
     */
    public String getFileExtension() {
        if (StringUtils.isBlank(fileName) || isDirectoryShare()) {
            return "";
        }

        int lastDotIndex = fileName.lastIndexOf('.');
        return lastDotIndex > 0 ? fileName.substring(lastDotIndex + 1).toLowerCase() : "";
    }

    /**
     * 获取文件图标类型
     * @return 文件图标类型
     */
    public String getIconType() {
        if (isDirectoryShare()) {
            return "folder";
        }

        String extension = getFileExtension();
        if (StringUtils.isBlank(extension)) {
            return "file";
        }

        // 根据文件扩展名确定图标类型（与FileVO中的逻辑一致）
        switch (extension) {
            case "jpg":
            case "jpeg":
            case "png":
            case "gif":
            case "bmp":
            case "webp":
                return "image";
            case "mp4":
            case "avi":
            case "mkv":
            case "mov":
            case "wmv":
            case "flv":
                return "video";
            case "mp3":
            case "wav":
            case "flac":
            case "aac":
            case "ogg":
            case "wma":
                return "audio";
            case "pdf":
                return "pdf";
            case "doc":
            case "docx":
                return "word";
            case "xls":
            case "xlsx":
                return "excel";
            case "ppt":
            case "pptx":
                return "powerpoint";
            case "txt":
            case "md":
                return "text";
            case "zip":
            case "rar":
            case "7z":
            case "tar":
            case "gz":
                return "archive";
            default:
                return "file";
        }
    }

    /**
     * 获取创建时间的相对描述
     * @return 相对时间描述
     */
    public String getRelativeCreateTime() {
        if (createTime == null) {
            return "";
        }

        LocalDateTime now = LocalDateTime.now();
        java.time.Duration duration = java.time.Duration.between(createTime, now);

        long days = duration.toDays();
        long hours = duration.toHours();
        long minutes = duration.toMinutes();

        if (days > 0) {
            return days + "天前";
        } else if (hours > 0) {
            return hours + "小时前";
        } else if (minutes > 0) {
            return minutes + "分钟前";
        } else {
            return "刚刚";
        }
    }

    /**
     * 初始化扩展字段
     */
    public void initializeExtendedFields() {
        getFormattedFileSize();
        getStatusDescription();
        getShareTypeDescription();
        getExpireStatusDescription();
        hasPasswordProtection();
        getRemainingHours();
    }

    /**
     * 清理敏感信息（用于公开API）
     * @return 清理后的VO副本
     */
    public ShareVO sanitizeForPublicApi() {
        ShareVO sanitized = new ShareVO();
        sanitized.setId(this.id);
        sanitized.setFileId(this.fileId);
        sanitized.setFileName(this.fileName);
        sanitized.setFileType(this.fileType);
        sanitized.setFileSize(this.fileSize);
        sanitized.setIsDirectory(this.isDirectory);
        sanitized.setShareCode(this.shareCode);
        sanitized.setShareUrl(this.shareUrl);
        sanitized.setExpireTime(this.expireTime);
        sanitized.setAccessCount(this.accessCount);
        sanitized.setIsPublic(this.isPublic);
        sanitized.setStatus(this.status);
        sanitized.setCreateTime(this.createTime);
        // 不复制用户ID和密码等敏感信息
        return sanitized;
    }
}